package cn.wangqi.personal.redis;

import redis.clients.jedis.*;
import redis.clients.util.SafeEncoder;

import java.io.Serializable;
import java.util.*;

public class RedisTemplate {
	    
	    private JedisPool jedisPool;

	    public RedisTemplate() {
	    }
	    	 
		public JedisPool getJedisPool() {
			return jedisPool;
		}

		public void setJedisPool(JedisPool jedisPool) {
			this.jedisPool = jedisPool;
		}

		/**
		 * 获取Jedis实例
		 * 
		 * @return
		 */
		public Jedis getJedis() {
			try {
				if (jedisPool != null) {
					Jedis resource = jedisPool.getResource();
					return resource;
				} else {
					return null;
				}
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}

		/**
		 * 释放jedis资源
		 * 
		 * @param jedis
		 */
		public void returnJedis(final Jedis jedis) {
			if (jedis != null) {
				jedis.close();
				//jedisPool.returnResource(jedis);
			}
		}
		
		/**
		 * 释放jedis资源
		 * 
		 * @param jedis
		 */
		public void returnBrokenJedis(final Jedis jedis) {
			if (jedis != null) {
				jedis.close();
				//jedisPool.returnBrokenResource(jedis);
			}
		}


	    // -------------------------基础操作-------------------------
	    public Long delKey(String... key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.del(key);
	        } catch (Exception e) {
	        	returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException("Deleting key failed: " + e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Boolean exists(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.exists(key);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public String rename(String oldkey, String newKey) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.rename(oldkey, newKey);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Long incrBy(final String key, final long integer) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.incrBy(key, integer);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Long inc(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.incr(key);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Long decrBy(final String key, final long integer) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.decrBy(key, integer);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Long decr(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.decr(key);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Set<String> keys(String pattern) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.keys(pattern);

	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException("Deleting key failed: " + e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }
	    //--------------------------基础操作结束-----------------------

	    // -------------------------list操作 start-------------------------
	    public <T extends Serializable> Long lpush(String key, T v) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.lpush(getKeyByte(key), RedisUtil.encode(v));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public <T extends Serializable> Long rpush(String key, T v) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.rpush(getKeyByte(key), RedisUtil.encode(v));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }


	    public <T extends Serializable> Long sadd(String key, T... v) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[][] bytes = RedisUtil.encode(v);
	            return redis.sadd(getKeyByte(key), bytes);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> T spop(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] result = redis.spop(getKeyByte(key));
	            if (result != null && result.length > 0) {
	                return (T) RedisUtil.decode(result);
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> List<T> lrange(String key, int start, int end) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            List<byte[]> result = redis.lrange(getKeyByte(key), start, end);
	            if (result != null && result.size() > 0) {
	                return (List<T>) RedisUtil.decode(result);
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
		public <T extends Serializable> T rpop(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] result = redis.rpop(getKeyByte(key));
	            if (result != null && result.length > 0) {
	                return (T) RedisUtil.decode(result);
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> T lpop(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] result = redis.lpop(getKeyByte(key));
	            if (result != null && result.length > 0) {
	                return (T) RedisUtil.decode(result);
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> List<T> blpop(int timeout, String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            List<byte[]> result = redis.blpop(timeout, getKeyByte(key));
	            if (result.size() == 0) {
	                return new ArrayList<T>(0);
	            }
	            return (List<T>) RedisUtil.decode(result, 1, result.size() - 1);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public <T extends Serializable> Long llen(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.llen(key);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /*
	     * 有序集合的操作
	     *
	     */
	    public <T extends Serializable> Long zadd(String key, double score, T v) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.zadd(getKeyByte(key), score, RedisUtil.encode(v));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Set<String> zrange(String key, long start, long end) {

	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            Set<String> result = redis.zrange(key, start, end);
	            if (result != null && !result.isEmpty()) {
	                return result;
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Long zrem(final String key, final String... members) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            Long result = redis.zrem(key, members);
	            return result;
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    // -------------------------list操作 end-------------------------

	    // -------------------------hash操作 start-------------------------
	    public <T extends Serializable> Long hset(String key, String filed, T v) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.hset(getKeyByte(key), getKeyByte(filed), RedisUtil.encode(v));

	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public <T extends Serializable> String hmset(String key, Map<String, T> fieldMap) {
	        Jedis redis = null;
	        Map<byte[], byte[]> bytesMap = null;
	        try {
	            redis = getJedis();
	            bytesMap = new HashMap<byte[], byte[]>();
	            for (Map.Entry<String, T> entry : fieldMap.entrySet()) {
	                byte[] value;
	                value = RedisUtil.encode(entry.getValue());
	                bytesMap.put(getKeyByte(entry.getKey()), value);
	            }

	            return redis.hmset(getKeyByte(key), bytesMap);

	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (bytesMap != null) {
	                bytesMap.clear();
	            }
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public long hdel(String key, String... fields) {
	        if (fields == null || fields.length == 0) {
	            return 0;
	        }

	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.hdel(key, fields);

	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public long hdel(String key, List<String> fields) {
	        if (fields == null || fields.size() == 0) {
	            return 0;
	        }

	        return hdel(key, fields.toArray(new String[fields.size()]));
	    }

	    public List<String> hkeys(String key) {
	        Jedis redis = null;
	        List<String> keys = new ArrayList<String>();
	        try {
	            redis = getJedis();
	            Set<byte[]> keySet = redis.hkeys(getKeyByte(key));
	            Iterator<byte[]> it = keySet.iterator();
	            while (it.hasNext()) {
	                keys.add(SafeEncoder.encode(it.next()));
	            }

	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	        return keys;
	    }


	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> T hget(String key, String filed) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] result = redis.hget(getKeyByte(key), getKeyByte(filed));
	            if (result != null && result.length > 0) {
	                return (T) RedisUtil.decode(result);
	            } else {
	                return null;
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> List<T> hmget(String key, String... fields) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[][] bytes = new byte[fields.length][];
	            for (int i = 0; i < fields.length; i++) {
	                bytes[i] = getKeyByte(fields[i]);
	            }
	            List<byte[]> result = redis.hmget(getKeyByte(key), bytes);
	            List<T> retList = new ArrayList<T>(result.size());
	            for (int i = 0; i < result.size(); i++) {
	                byte[] byteValue = result.get(i);
	                if (byteValue == null) {
	                    retList.add(null);
	                } else {
	                    retList.add((T) RedisUtil.decode(byteValue));
	                }
	            }

	            result.clear();

	            return retList;
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }
	    // -------------------------hash操作 end-------------------------

	    // -------------------------SET操作-------------------------
	    public <T extends Serializable> String set(String key, T value) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.set(getKeyByte(key), RedisUtil.encode(value));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /**
	     * 用于计数器, 注意:set api不能满足计数器的需求。
	     *
	     * @param key     计数器key
	     * @param seconds 过期时间(秒), 如果值小于1, 视为永不过期。
	     * @param value   计数器的值
	     * @return
	     */
	    public String setCounter(String key, int seconds, int value) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            if (seconds < 1) {//永不过期
	                return redis.set(key, value + "");
	            } else {
	                return redis.setex(key, seconds, value + "");
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /**
	     * 获取计数器值, 如果key不存在,则返回-1.
	     *
	     * @param key 计数器key
	     * @return 如果key不存在, 返回-1
	     */
	    public int getCounter(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            String val = redis.get(key);
	            return val ==null||val.length() == 0 ? -1:Integer.parseInt(val);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public <T extends Serializable> String setex(String key, int seconds, T value) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.setex(getKeyByte(key), seconds, RedisUtil.encode(value));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public <T extends Serializable> Long setnx(String key, T value) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.setnx(getKeyByte(key), RedisUtil.encode(value));
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /**
	     * This method need some testing.
	     */
	    public <T extends Serializable> void mSet(Map<String, T> keyValueMap) {

	        Jedis redis = null;
	        if (keyValueMap == null || keyValueMap.size() == 0) {
	            throw new RuntimeException("There is no data in map.");
	        }
	        try {
	            redis = getJedis();
	            byte[][] data = RedisUtil.encode(keyValueMap);
	            redis.mset(data);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /**
	     * This method need some testing.
	     */
	    public <T extends Serializable> Long mSetnx(
	            Map<String, T> keyValueMap) {

	        if (keyValueMap == null || keyValueMap.size() == 0) {
	            throw new RuntimeException("There is no data in map.");
	        }

	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[][] data = RedisUtil.encode(keyValueMap);
	            return redis.msetnx(data);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> T get(String key) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] value = redis.get(getKeyByte(key));
	            if (null == value) {
	                return null;
	            } else {
	                return (T) RedisUtil.decode(value);
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    @SuppressWarnings("unchecked")
	    public <T extends Serializable> List<T> mGet(String... keys) {
	        byte[][] bkeys = new byte[keys.length][];
	        for (int i = 0; i < bkeys.length; i++) {
	            bkeys[i] = SafeEncoder.encode(keys[i]);
	        }
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            List<byte[]> result = redis.mget(bkeys);
	            if (result == null || result.size() == 0) {
	                return null;
	            } else {
	                return (List<T>) RedisUtil.decode(result);
	            }
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }
	    // -------------------------POJO操作 end-------------------------

	    public List<byte[]> lrangeBytes(String key, int start, int end) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.lrange(getKeyByte(key), start, end);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    // -------------------------事务操作 begin-------------------------

	    public Jedis watch(String... keys) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            redis.watch(keys);
	            return redis;
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public String unWatch(Jedis redis) {
	        if (redis == null) {
	            return null;
	        }

	        try {
	            return redis.unwatch();
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public Transaction mutil(Jedis redis) {
	        if (redis == null) {
	            return null;
	        }
	        return redis.multi();
	    }

	    public <T extends Serializable> Long sadd(String key, T v, Transaction ts) {
	        try {
	            Response<Long> resp = ts.sadd(getKeyByte(key), RedisUtil.encode(v));
	            if (resp == null) {
	                return -1L;
	            }
	            return resp.get();
	        } catch (Exception e) {
	            throw new RuntimeException(e.getMessage(), e);
	        }
	    }

	    /**
	     * expire key with seconds
	     *
	     * @param key     -String
	     * @param seconds -int
	     * @param <T>     long
	     * @return
	     */
	    public <T extends Serializable> Long expire(String key, int seconds) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            return redis.expire(getKeyByte(key), seconds);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    /**
	     * This method need testing.
	     */
	    public <T extends Serializable> String set(String key, T v, Transaction ts) {
	        try {
	            Response<String> resp = ts.set(getKeyByte(key), RedisUtil.encode(v));
	            if (resp == null) {
	                return null;
	            }
	            return resp.get();
	        } catch (Exception e) {
	            throw new RuntimeException(e.getMessage(), e);
	        }
	    }


	    public <T extends Serializable> void publish(String channel, T msg) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            byte[] bytes = RedisUtil.encode(msg);
	            redis.publish(getKeyByte(channel), bytes);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    public void subscribe(final String channel, PubSubListener listener) {
	        Jedis redis = null;
	        try {
	            redis = getJedis();
	            Client client = redis.getClient();
	            listener.proceed(client, channel);
	        } catch (Exception e) {
	            returnBrokenJedis(redis);
	            redis = null;
	            throw new RuntimeException(e.getMessage(), e);
	        } finally {
	            if (null != redis) {
	                returnJedis(redis);
	            }
	        }
	    }

	    // -------------------------事务操作 end-------------------------
	    private byte[] getKeyByte(String key) {
	        return SafeEncoder.encode(key);
	    }

	}
